package org.aldar.bquest.screens;

import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.net.Uri;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Window;
import android.view.WindowManager;
import org.aldar.bquest.constants.GameCycleState;
import org.aldar.bquest.constants.IConstants;
import org.aldar.bquest.entity.LoggedScene;
import org.aldar.bquest.entity.pool.TilesPool;
import org.aldar.bquest.logic.TilesGameCycle;
import org.aldar.bquest.logic.controller.board.TouchAndMoveController;
import org.aldar.bquest.logic.controller.entity.HeroAnimationController;
import org.aldar.bquest.logic.controller.level.LevelController;
import org.aldar.bquest.logic.controller.player.ManaAndPointsController;
import org.aldar.bquest.logic.layout.ScreenContentManager;
import org.aldar.bquest.profile.GameProfile;
import org.aldar.bquest.resources.ResourceManager;
import org.aldar.bquest.sound.GameSound;
import org.aldar.bquest.util.*;
import org.andengine.engine.Engine;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.handler.IUpdateHandler;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.scene.CameraScene;
import org.andengine.entity.scene.ITouchArea;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.Sprite;
import org.andengine.opengl.texture.Texture;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;

import java.io.IOException;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

public class MainBoardScreen extends ScreenWithInterstitialBanner implements IConstants {

    protected Scene mMainScene;
    protected Scene splashScene;
    private SQLiteHelper mSQLiteHelper = new SQLiteHelper(this);

    private GameSound gameSound;
    private ScoreCounter scoreCounter;
    ScreenContentManager scm;

    protected CameraScene mLoadScreen;
    protected int TextureCount;
    protected Sprite progressBar;
    protected long loadStart;
    protected long loadFinish;
    protected long prevLoaded;
    protected long textureLoadStarted;

    private ITextureRegion loadingScreenBgTextureRegion;
    private ITextureRegion loadingScreenBarFrameTextureRegion;
    private ITextureRegion loadingScreenBarProgressTextureRegion;


    private static final Logger LOG = new Logger(MainBoardScreen.class);


    public static MainBoardScreen screenInstance = null;
    private boolean isBannerEnabled = true;

    private boolean gamePaused = false;

    protected Scene mSplashScene;
    private boolean isConfirmBackToMapPopupShown;
    private Runnable backButtonAction = null;

    public static MainBoardScreen getInstance() {
        return screenInstance;
    }

    protected Camera mCamera;


    @Override
    public EngineOptions onCreateEngineOptions() {
        mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
        EngineOptions opts = new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED,//TODO replaced "PORTRAIT"
                new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), mCamera);
        opts.getAudioOptions().setNeedsSound(true);
        opts.getAudioOptions().setNeedsMusic(true);
        opts.getRenderOptions().setDithering(true);
        return opts;
    }


    protected void onCreateResources() throws IOException {
        BitmapTextureAtlas t = new BitmapTextureAtlas(this.getTextureManager(), 480, 800, TextureOptions.DEFAULT);
        loadingScreenBgTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loading_screen_bg.png", 0, 0);
        t.load();
        t = new BitmapTextureAtlas(this.getTextureManager(), 280, 27, TextureOptions.DEFAULT);
        loadingScreenBarFrameTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loadingbar_frame.png", 0, 0);
        t.load();
        t = new BitmapTextureAtlas(this.getTextureManager(), 270, 21, TextureOptions.DEFAULT);
        loadingScreenBarProgressTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(t, this, "gfx/common/loadingbar_progress.png", 0, 0);
        t.load();

        loadResources();
    }

    protected void createLoadScreen() {
        mLoadScreen = new CameraScene(mCamera);
        mLoadScreen.setBackgroundEnabled(false);
        Sprite bg = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2, loadingScreenBgTextureRegion, getVertexBufferObjectManager());
        Sprite barFrame = new Sprite(CAMERA_WIDTH / 2, CAMERA_HEIGHT / 2 - 17, loadingScreenBarFrameTextureRegion, getVertexBufferObjectManager());
        progressBar = new Sprite(CAMERA_WIDTH / 2 - loadingScreenBarProgressTextureRegion.getWidth() / 2, CAMERA_HEIGHT / 2 - 17, loadingScreenBarProgressTextureRegion, getVertexBufferObjectManager());
        progressBar.setAnchorCenter(0, 0.5f);
        progressBar.setScaleX(0);
        mLoadScreen.attachChild(bg);
        mLoadScreen.attachChild(progressBar);
        mLoadScreen.attachChild(barFrame);
        mMainScene.setChildScene(mLoadScreen, false, true, true);
        mMainScene.setChildrenIgnoreUpdate(true);
    }

    public void loadTextures(final boolean pResume) {
        final List<Texture> mAllTextures = ResourceManager.getInstance().getmAllTextures();
        final List<String> mAllTextureNames = ResourceManager.getInstance().getmAllTextureNames();
        TextureCount = -1;
        LOG.i("Echo", "Begin Load - T: " + TextureCount + " - pResume: " + pResume);
        loadStart = new Date().getTime();
        mLoadScreen.registerUpdateHandler(new IUpdateHandler() {
            @Override
            public void onUpdate(float pSecondsElapsed) {
                TextureCount++;
                if (prevLoaded != 0) {
                    LOG.i("Echo", "Prev load: " + (new Date().getTime() - prevLoaded) + " ms.");
                }
                prevLoaded = new Date().getTime();
                if (TextureCount < ResourceManager.getInstance().getmAllTextures().size()) {
                    mEngine.getTextureManager().loadTexture(mAllTextures.get(TextureCount));
                    LOG.i("Echo", "Loaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size() + ". filename: " + mAllTextureNames.get(TextureCount));
                    for (int i = 0; i < 5; i++) {
                        TextureCount++;
                        if (TextureCount < ResourceManager.getInstance().getmAllTextures().size()) {
                            mEngine.getTextureManager().loadTexture(mAllTextures.get(TextureCount));
                            LOG.i("Echo", "Loaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size() + ". filename: " + mAllTextureNames.get(TextureCount));
                        }
                    }
                    if (progressBar.getEntityModifierCount() == 0) {
                        progressBar.registerEntityModifier(new ScaleModifier(0.3f, progressBar.getScaleX(), Math.min(((float) TextureCount) / mAllTextures.size(), 1f), 1, 1));
                    }

                } else {
                    mLoadScreen.unregisterUpdateHandler(this);
                    mLoadScreen.detachChildren();
                    mEngine.getFontManager().onReload();
                    loadFinish = new Date().getTime();
                    LOG.i("Echo Loaded textures in " + (loadFinish - loadStart) + " ms.");
                    if (pResume) {
                        LOG.i("Echo", "Textures Loaded, Resuming...");
                        mMainScene.back();
                        mMainScene.setChildrenIgnoreUpdate(false);
                    } else {
                        LOG.i("Echo", "Textures Loaded, proceeding to MainMenu");
                        // set scene to main menu or however your project is setup
                        mMainScene.clearChildScene();
                        mMainScene.setChildrenIgnoreUpdate(false);
                    }
                }
            }

            @Override
            public void reset() {
            }
        });
    }

    public void loadResources() {
        try {
            ResourceManager.getInstance().loadResources(getTextureManager(), getFontManager(), getSoundManager(), getVertexBufferObjectManager(), this);
        } catch (IOException e) {
            LOG.e("Exception onCreateResources", e);
        }

    }

    @Override
    protected Scene onCreateScene() {
        long millis1 = new Date().getTime();
        loadResources();
        long millis2 = new Date().getTime();
        LOG.i("tLoaded resources ms: " + (millis2 - millis1));

        loadMainScene();
        long millis3 = new Date().getTime();
        LOG.i("tLoaded MainScene ms: " + (millis3 - millis2));
        mEngine.setScene(mMainScene);
        mMainScene.setChildrenIgnoreUpdate(false);

        createLoadScreen();
        long millis4 = new Date().getTime();
        LOG.i("tLoaded ChildScene ms: " + (millis4 - millis3));

        loadTextures(false);

/*        mMainScene.registerUpdateHandler(new IUpdateHandler() {
            @Override
            public void onUpdate(float pSecondsElapsed) {
                if (mPreloadGraphicTexture.isLoadedToHardware()) {
                    mMainScene.unregisterUpdateHandler(this);
                    createLoadScreen();
                    loadTextures(false);
                    // boolean true if resuming - more on this later
                }
            }

            @Override
            public void reset() {
            }
        });
  */
        return mMainScene;
    }

    @Override
    public void onResume() {
        //getEngine().setLastRealTimeMeasurement(0);
        try {
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
            if (audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) > 5) {
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 5, 0);
            }
            getGameSound().playMainLoopSound();
        } catch (Exception e) {
            LOG.e("Cannot start playing music on activity resume", e);
        }
        this.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Log.i("aldar111", "onResume");
        super.onResume();
        TilesGameCycle.getInstance().setGameRunning(true);


        final List<Texture> mAllTextures = ResourceManager.getInstance().getmAllTextures();

        //added from loadTextures after commenting next block
        if (mMainScene != null)
            mMainScene.setChildrenIgnoreUpdate(false);

        /*
        if (mMainScene != null) {
            TextureCount = 0;
            mMainScene.registerUpdateHandler(new IUpdateHandler() {
                @Override
                public void onUpdate(float pSecondsElapsed) {
                    mEngine.getTextureManager().unloadTexture(mPreloadGraphicTexture);
                    if (!mPreloadGraphicTexture.isLoadedToHardware()) {
                        mMainScene.unregisterUpdateHandler(this);
                        mMainScene.registerUpdateHandler(new IUpdateHandler() {
                            @Override
                            public void onUpdate(float pSecondsElapsed) {
                                mEngine.getTextureManager().loadTexture(mPreloadGraphicTexture);
                                if (mPreloadGraphicTexture.isLoadedToHardware()) {
                                    mMainScene.unregisterUpdateHandler(this);
                                    mMainScene.setChildScene(mLoadScreen, false, true, true);
                                    mMainScene.setChildrenIgnoreUpdate(true);
                                    if (progressBar != null) {
                                        progressBar.setScaleX(0);
                                    }
                                    mLoadScreen.registerUpdateHandler(new IUpdateHandler() {
                                        @Override
                                        public void onUpdate(float pSecondsElapsed) {
                                            if (TextureCount < mAllTextures.size()) {
                                                mEngine.getTextureManager().unloadTexture(mAllTextures.get(TextureCount));
                                                LOG.i("Echo", "UnLoaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size());
                                                for (int i = 0; i < 20; i++) {
                                                    TextureCount++;
                                                    if (TextureCount < mAllTextures.size()) {
                                                        mEngine.getTextureManager().unloadTexture(mAllTextures.get(TextureCount));
                                                        LOG.i("Echo", "UnLoaded texture: " + (TextureCount + 1) + " of " + mAllTextures.size());
                                                    }
                                                }
                                            } else {
                                                if (!mAllTextures.get(mAllTextures.size() - 1).isLoadedToHardware()) {
                                                    mLoadScreen.unregisterUpdateHandler(this);
                                                    LOG.i("Echo", "UnLoading complete");
                                                    loadTextures(true);
                                                } else {
                                                    TextureCount++;
                                                }
                                            }
                                        }

                                        @Override
                                        public void reset() {
                                        }
                                    });
                                }
                            }

                            @Override
                            public void reset() {
                            }
                        });
                    }
                }

                @Override
                public void reset() {
                }
            });
        } else {
            LOG.i("Echo", "ON RESUME");
        }
        */
        super.onResume();
    }


    private Scene loadMainScene() {

        long millis12 = new Date().getTime();
        //LOG.i("tLoaded hero ms: " + (millis12 - millis11));

        screenInstance = this;

        LOG.i("Creating scene");

        scoreCounter = ScoreCounter.getInstance();
        gameSound = new GameSound(this, this.mEngine.getSoundManager(), mEngine.getMusicManager());
        GameSound.setCurrentInstance(gameSound);
        TilesGameCycle gameCycle = TilesGameCycle.getInstance();
        SQLiteHelper.setCurrentInstance(mSQLiteHelper);

        this.mMainScene = new LoggedScene(this) {
            public String toString() {
                return "mainScene";
            }
        };
        this.mMainScene.setBackgroundEnabled(true);
        this.mMainScene.setOnSceneTouchListener(new TouchAndMoveController());
        this.mMainScene.registerUpdateHandler(gameCycle);

        scm = new ScreenContentManager();

        scm.setMainScene(mMainScene);
        scm.setVertexBufferObjectManager(getVertexBufferObjectManager());
        if (GameProfile.selectedLevelAreaIndex == null || GameProfile.selectedLevelIndex == null) {
            Log.e("EXCEPTION ALDAR", "cannot start main board when no level is selected!! Perhaps the activity has been restarted due to offline timeout. Redirecting to levelMapScreen");
            Intent intent = new Intent();
            intent.setClass(MainBoardScreen.screenInstance.getApplicationContext(), LevelMapScreen.class);
            MainBoardScreen.screenInstance.startActivity(intent);
            MainBoardScreen.screenInstance.finish();
            return this.mMainScene;
        }

        scm.initLayers();
        TestUtil testUtil = new TestUtil();
        mMainScene.setChildrenIgnoreUpdate(true);

        TilesGameCycle.getInstance().setState(GameCycleState.WAITING);
        TilesPool.clearPool();

        LevelController levelController = new LevelController();
        HeroAnimationController heroController = new HeroAnimationController();

        levelController.initLevel();

        ManaAndPointsController manaAndPointsController = new ManaAndPointsController();


        manaAndPointsController.setBonusLayer(ScreenContentManager.getScreenContentManager().getBonusLayer());
        manaAndPointsController.setVertexBufferObjectManager(getVertexBufferObjectManager());
        manaAndPointsController.initEmptyManaAndSkills();
        getGameSound().initSound();        //开场效果
        this.prepareGame();
        LOG.i("Finished creating scene");
        return this.mMainScene;


    }

    public static ScreenContentManager getScm() {
        return screenInstance.scm;
    }

    public static Engine getInstanceEngine() {
        return screenInstance.mEngine;
    }

    @Override
    public boolean isBannerEnabled() {
        return isBannerEnabled;
    }

    /*@Override
    protected void onSetContentView() {
        mRenderSurfaceView = new RenderSurfaceView(this);
        mRenderSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 24, 0);
        mRenderSurfaceView.setRenderer(mEngine, this);
        mRenderSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);

        this.setContentView(mRenderSurfaceView, BaseGameActivityMy.createSurfaceViewLayoutParams());
    }    */


    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        Window window = getWindow();
        window.setFormat(PixelFormat.RGBA_8888);
    }

    @Override
    protected void onPause() {
        Log.i("aldar111", "onPause");
        Log.i("aldar1112", "" + MainBoardScreen.getInstance());
        Log.i("aldar1113", "" + MainBoardScreen.getScm());


        try {
            getGameSound().stopMainLoopSound();
            getGameSound().stopTicTacSound();
            mMainScene.setChildrenIgnoreUpdate(true);
            super.onPause();
            TilesGameCycle.getInstance().setGameRunning(false);
            if (!gamePaused && (LevelController.getCurrentLevelState() == LevelController.LevelState.PROGRESS
                    || LevelController.getCurrentLevelState() == LevelController.LevelState.PREPARE)) {
                //showGamePausedPopup();
            }
        } catch (Exception e) {
            Log.e("aldar", "Exception while trying to show Pause popup in onPause method", e);
            gotoStartMenuScreen();
        }
    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (backButtonAction != null) {
                runOnUpdateThread(backButtonAction);
                backButtonAction = null;
            } else if (!isConfirmBackToMapPopupShown && LevelController.getCurrentLevelState() == LevelController.LevelState.PROGRESS) {
                showConfirmBackToMapPopoup();
            }
            return true;
        }
        return super.onKeyDown(keyCode, event);    //To change body of overridden methods use File | Settings | File Templates.
    }

    private void showConfirmBackToMapPopoup() {
        getScm().setBgTouchAreas(false, false);

        Sprite levelResultsBg = new Sprite(0, 0, getScm().getConfirmationBgTextureRegion(), MainBoardScreen.getScm().getVertexBufferObjectManager());
        final List<ITouchArea> touchAreasForPopup = new LinkedList<ITouchArea>();
        levelResultsBg.setAnchorCenter(0, 0);
        MainBoardScreen.getScm().getTutorialLayer().attachChild(levelResultsBg);
        CustomButtonSprite buttonYes = new CustomButtonSprite(CAMERA_WIDTH / 2 - 50, CAMERA_HEIGHT / 2 - 55, getScm().getButtonYesTextureRegion().getTextureRegion(0),
                getScm().getButtonYesTextureRegion().getTextureRegion(1), getVertexBufferObjectManager(), new CustomButtonSprite.OnClickListener() {
            @Override
            public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                gotoLevelMapScreen();
            }
        });
        CustomButtonSprite buttonNo = new CustomButtonSprite(CAMERA_WIDTH / 2 + 50, CAMERA_HEIGHT / 2 - 55, getScm().getButtonNoTextureRegion().getTextureRegion(0),
                getScm().getButtonNoTextureRegion().getTextureRegion(1), getVertexBufferObjectManager(), new CustomButtonSprite.OnClickListener() {
            @Override
            public void onClick(CustomButtonSprite pButtonSprite, float pTouchAreaLocalX, float pTouchAreaLocalY) {
                getScm().setBgTouchAreas(true, true);
                unregisterTouchAreas(touchAreasForPopup);
                isConfirmBackToMapPopupShown = false;
                runOnUpdateThread(new Runnable() {
                    @Override
                    public void run() {
                        MainBoardScreen.getScm().getTutorialLayer().detachChildren();
                    }
                });
            }
        });

        MainBoardScreen.getScm().getTutorialLayer().attachChild(buttonYes);
        MainBoardScreen.getScm().getMainScene().registerTouchArea(buttonYes);
        touchAreasForPopup.add(buttonYes);

        MainBoardScreen.getScm().getTutorialLayer().attachChild(buttonNo);
        MainBoardScreen.getScm().getMainScene().registerTouchArea(buttonNo);
        touchAreasForPopup.add(buttonNo);
        isConfirmBackToMapPopupShown = true;
    }

    private void unregisterTouchAreas(List<ITouchArea> toUnregister) {
        for (ITouchArea item : toUnregister) {
            MainBoardScreen.getScm().getMainScene().unregisterTouchArea(item);
        }
    }

    private void prepareGame() {
        this.mMainScene.registerUpdateHandler(new TimerHandler(1.0f, new ITimerCallback() {
            @Override
            public void onTimePassed(final TimerHandler pTimerHandler) {
                mMainScene.unregisterUpdateHandler(pTimerHandler);
                TilesGameCycle.getInstance().setGameRunning(true);
            }
        }));
    }

    public GameSound getGameSound() {
        return gameSound;
    }

    public ScoreCounter getScoreCounter() {
        return scoreCounter;
    }

    @Deprecated
    public static SQLiteHelper getmSQLiteHelper() {
        return SQLiteHelper.getCurrentInstance();
    }

    public void gotoLevelMapScreen() {
        Intent intent = new Intent();
        intent.setClass(MainBoardScreen.screenInstance.getApplicationContext(), LevelMapScreen.class);
        MainBoardScreen.screenInstance.startActivity(intent);
        MainBoardScreen.screenInstance.finish();
    }

    public void gotoStartMenuScreen() {
        Intent intent = new Intent();
        intent.setClass(MainBoardScreen.screenInstance.getApplicationContext(), StartMenuScreen.class);
        MainBoardScreen.screenInstance.startActivity(intent);
        MainBoardScreen.screenInstance.finish();
    }

    public Runnable getBackButtonAction() {
        return backButtonAction;
    }

    public void setBackButtonAction(Runnable backButtonAction) {
        this.backButtonAction = backButtonAction;
    }

    public void rateAppButtonAction() {
        startActivity(new Intent(
                Intent.ACTION_VIEW, Uri
                .parse("market://details?id="
                        + "org.aldar.bquest")));

    }

}
